package com.example.service.flowable.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.pojo.Emp;
import com.example.service.flowable.FlowableServiceAbstract;
import com.example.service.flowable.ILeaveService;
import com.example.vo.ResultVo;
import com.example.vo.process.EvectionDetailVo;
import com.example.vo.process.LeaveVo;
import com.example.vo.process.com.ProInst;
import com.example.vo.process.com.ProNode;
import liquibase.pro.packaged.e;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.*;

/**
 * 请假申请服务实现类
 * @author wsl
 */
@Service
public class LeaveServiceImpl extends FlowableServiceAbstract implements ILeaveService {

    public LeaveServiceImpl(@Value("${process-definition-id.leave}") String processDefinitionId) {
        super(processDefinitionId);
    }

    @Override
    public ResultVo createLeaveProcess(LeaveVo leaveVo) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("beginTime",leaveVo.getBeginTime());
        variables.put("endTime",leaveVo.getEndTime());
        variables.put("cause",leaveVo.getCause());
        variables.put("days",leaveVo.getDays());
        variables.put("holidayType",leaveVo.getHolidayType());
        variables.put("holidayTypeName",leaveVo.getHolidayTypeName());
        variables.put("startUserName",leaveVo.getStartUserName());
        variables.put("leader",leaveVo.getLeaderAssignee());
        variables.put("hrSpecialist",leaveVo.getPerAssignee());
        Authentication.setAuthenticatedUserId(leaveVo.getStartUser());//设置流程的发起人
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceById(processDefinitionId, variables);
        return ResultVo.response(processInstance.getId());
    }

    @Override
    public ResultVo queryAssessingOfficer(String userId) {
        Map<String, Object> assessingOfficers = new HashMap<>();
        ///1、查询用户上级
        Emp empSuperior = selectEmpSuperior(userId);
        assessingOfficers.put("superior",empSuperior);
        //2、查询人事专员
        List<Emp> hrSpecialist = selectHrSpecialist();
        assessingOfficers.put("hrSpecialist",hrSpecialist);
        return ResultVo.response(assessingOfficers);
    }

    @Override
    public ResultVo queryMyLeaveProcess(String userId) {
        List<HistoricProcessInstance> list = historyService
                .createHistoricProcessInstanceQuery()
                .processDefinitionId(processDefinitionId)
                .startedBy(userId)
                .includeProcessVariables()
                .orderByProcessInstanceStartTime()
                .desc()
                .list();
        List<LeaveVo> leaveVos = new ArrayList<>();
        list.forEach(e->{
            Map<String, Object> processVariables = e.getProcessVariables();
            LeaveVo leaveVo = new LeaveVo();
            leaveVo.setProcessInstanceId(e.getId())
                    .setBeginTime((Date)processVariables.get("beginTime"))
                    .setCause((String) processVariables.get("cause"))
                    .setDays((Integer)processVariables.get("days"))
                    .setEndTime((Date)processVariables.get("endTime"))
                    .setHolidayType((String) processVariables.get("holidayType"))
                    .setHolidayTypeName((String)processVariables.get("holidayTypeName"))
                    .setStartUser(e.getStartUserId())
                    .setStartUserName((String)processVariables.get("startUserName"))
                    .setLeaderAssignee((String)processVariables.get("leader"))
                    .setPerAssignee((String)processVariables.get("hrSpecialist"))
                    .setApplicDate(e.getStartTime());
            if(e.getEndTime()!=null){//流程已结束
                leaveVo.setEnd(true);
                leaveVo.setApproved((Boolean)processVariables.get("approved"));
            }else{
                HistoricActivityInstance historicActivityInstance = historyService
                        .createHistoricActivityInstanceQuery()
                        .processInstanceId(e.getId())
                        .unfinished()
                        .singleResult();
                //获取节点处理人信息
                leaveVo.setCurrentNode(historicActivityInstance.getActivityName());
                Emp assigneeEmp = selectAssigneeEmp(historicActivityInstance.getAssignee());
                leaveVo.setAssigneeEmp(assigneeEmp);
            }
            leaveVos.add(leaveVo);
        });
        return ResultVo.response(leaveVos);
    }

    @Override
    public ResultVo queryAuditTask(String userId) {
        List<Task> list = taskService
                .createTaskQuery()
                .processDefinitionId(processDefinitionId)
                .includeProcessVariables()
                .taskAssignee(userId)
                .list();
        List<LeaveVo> leaveVos = new ArrayList<>();
        for (Task task : list) {
            LeaveVo leaveVo = new LeaveVo();
            Map<String, Object> processVariables = task.getProcessVariables();
            leaveVo.setProcessInstanceId(task.getProcessInstanceId())
                    .setBeginTime((Date)processVariables.get("beginTime"))
                    .setCause((String) processVariables.get("cause"))
                    .setDays((Integer)processVariables.get("days"))
                    .setEndTime((Date)processVariables.get("endTime"))
                    .setHolidayType((String) processVariables.get("holidayType"))
                    .setHolidayTypeName((String)processVariables.get("holidayTypeName"))
                    .setStartUserName((String)processVariables.get("startUserName"))
                    .setLeaderAssignee((String)processVariables.get("leader"))
                    .setPerAssignee((String)processVariables.get("hrSpecialist"))
                    .setTaskId(task.getId())
                    .setTaskName(task.getName());
            leaveVos.add(leaveVo);
//            ProcessInstance processInstance = runtimeService
//                    .createProcessInstanceQuery()
//                    .processInstanceId(task.getProcessInstanceId())
//                    .singleResult();
//            empMapper.selectOne(processInstance.getStartUserId())
        }
        return ResultVo.response(leaveVos);
    }

    @Override
    public ResultVo completeExamineApproved(String taskId, Boolean approved, String reply) {
        taskService.setVariable(taskId,"approved",approved);
        taskService.setVariableLocal(taskId,"approved",approved);
        if(!StringUtils.isEmpty(reply)){
            taskService.setVariableLocal(taskId,"reply",reply);
        }
        taskService.complete(taskId);
        return ResultVo.ok();
    }

    @Override
    public ResultVo queryLeaveApplyDetail(String processInstanceId) {
        ProInst proInst = new ProInst();
        //1、查询请假流程实例信息
        HistoricProcessInstance historicProcessInstance = historyService
                .createHistoricProcessInstanceQuery()
                .processDefinitionId(processDefinitionId)
                .processInstanceId(processInstanceId)
                .includeProcessVariables()
                .singleResult();
        proInst.setVariables(historicProcessInstance.getProcessVariables())
                .setCreateTime(historicProcessInstance.getStartTime())
                .setEndTime(historicProcessInstance.getEndTime())
                .setIsEnd(historicProcessInstance.getEndTime()!=null)
                .setProcessInstanceId(historicProcessInstance.getId());
        //2、查询流程实例节点信息
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                .processDefinitionId(processDefinitionId)
                .processInstanceId(historicProcessInstance.getId())
                .includeTaskLocalVariables()
                .orderByTaskCreateTime()
                .desc()
                .list();
        List<ProNode> proNodeList = new ArrayList<>();
        list.forEach(e->{
            ProNode proNode = new ProNode();
            //查询代理人信息
            Emp emp = empMapper.selectById(e.getAssignee());
            proNode
                    .setAssignee(emp.getId().toString())
                    .setAssigneeName(emp.getEmpName())
                    .setDurationMillisecond(e.getDurationInMillis())
                    .setEndTime(e.getEndTime())
                    .setStartTime(e.getCreateTime())
                    .setNodeName(e.getName())
                    .setVariables(e.getTaskLocalVariables());
            proNodeList.add(proNode);
        });
        proInst.setProNodeList(proNodeList);
        return ResultVo.response(proInst);
    }

    @Override
    public ResultVo queryTaskDetail(String taskId) {
        ProInst proInst = new ProInst();
        Task task = taskService
                .createTaskQuery()
                .taskId(taskId)
                .singleResult();
        String processInstanceId = task.getProcessInstanceId();
        ProcessInstance processInstance = runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .includeProcessVariables()
                .singleResult();
        proInst
                .setCreateTime(processInstance.getStartTime())
                .setProcessInstanceId(processInstanceId)
                .setVariables(processInstance.getProcessVariables());
        return ResultVo.response(proInst);
    }

    public Emp selectEmpSuperior(String userId){
        Emp emp = empMapper.selectById(userId);
        if(emp==null){
            return null;
        }else{
            Wrapper<Emp> wrapper = new QueryWrapper<Emp>()
                    .select("id,emp_name")
                    .eq("id",emp.getSuperiorId());
            return empMapper.selectOne(wrapper);
        }
    }

    public List<Emp> selectHrSpecialist(){
        Wrapper<Emp> wrapper = new QueryWrapper<Emp>()
                .select("id,emp_name")
                .eq("dept_id",22);
        return empMapper.selectList(wrapper);
    }
}
